﻿using MongoDB.Bson;
using Net.http;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text.Json.Nodes;

namespace HBase {
    /**
   *┌────────────────────────────────────────────────┐
   *│　描    述：ObjectConvert                                                    
   *│　作    者：sgj                                              
   *│　版    本：1.0                                              
   *│　创建时间：2022-06-25 08:23:00                        
   *└────────────────────────────────────────────────┘
   **/
    public class JsonUtil {

        public static string simpleSerializeObject(object o) {
            string json = JsonConvert.SerializeObject(o);
            return json.Replace("\r\n", "");
        }
        public static string toView(Object obj) {
            if (obj == null) {
                return "";
            }
            String josn = simpleSerializeObject(obj);
            return unUseJson(josn);
        }



        public static String unUseJson(String v) {
            String res = $"\"";
            String param = v.Replace(res, "");
            if (param.Length >= 2) {
                param = param.Substring(1, param.Length - 2);
            }
            return param.Replace(" ", "");
        }

        public static string toJosn(Object obj) {
            if( obj == null ) {
                return "";
            }
            String josn = mySerializeObject(obj);
            return josn.Replace("\r\n" ,"").Replace(" " ,"");
        }
        public static T toObj<T>(String jsonStr) {
            if( string.IsNullOrEmpty(jsonStr) ) {
                return default(T);
            }
            return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(jsonStr);
        }

        public static string mySerializeObject(object o) {
            string json = JsonConvert.SerializeObject(o);
            return json;
        }
        public static BsonDocument def0(BsonDocument nowDoc) {
            BsonDocument bd = new BsonDocument();
            ;
            IEnumerable<BsonElement> elements = nowDoc.Elements;
            foreach( BsonElement be in elements ) {
                String name = be.Name;
                if( name == "path" ) {
                    continue;
                }
                BsonValue nowv = be.Value;
                var defValue = def2(nowv);
                if( defValue != null ) {
                    bd.Add(name ,defValue);
                }

            }
            return bd;
        }

        static BsonValue def2(BsonValue nowv) {
            if( nowv.IsBsonArray ) {
                BsonArray arrayNew = new BsonArray();
                BsonArray array = nowv.AsBsonArray;

                for( int i = 0;i < array.Count;i++ ) {
                    BsonDocument bdc = def0(array[i].AsBsonDocument);
                    if( bdc.ElementCount != 0 ) {
                        arrayNew.Add(bdc);
                    }
                }
                if( arrayNew.Count != 0 ) {
                    return arrayNew;
                }

            } else if( nowv.IsBsonDocument ) {

                BsonDocument defValue = def0(nowv.AsBsonDocument);
                if( defValue.ElementCount != 0 ) {
                    return defValue;
                }

            } else {
                if( "0" != nowv.ToString() ) {
                    return nowv;
                }
            }
            return null;
        }
        public T jsonConvert<T>(String value) {

            JObject jsonObject = JsonConvert.DeserializeObject<JObject>(value);

            if( jsonObject == null ) {
                return default(T);
            }



            return create<T>(jsonObject);
        }


         
       static T create<T>(JObject jsonObject) {
            Type type = typeof(T);
            T t = (T)Activator.CreateInstance(type);
            FieldInfo[] fields = type.GetFields();
            foreach (FieldInfo f in fields) {
                MappingNameAttribute mappingName = f.GetCustomAttribute<MappingNameAttribute>();
                JToken jt = getData(jsonObject, mappingName);
                f.SetValue(t, jt);

            }
            return t;
        }




        static public List<T> jsonArrayConvert<T>(String jsonStr, String key = null) {
            List<T> res = new List<T>();
            JObject jsonObject = JsonConvert.DeserializeObject<JObject>(jsonStr);

            if (jsonObject == null) {
                return res;
            }

            JToken jToken = jsonObject;
            if (key != null) {

                String[] keys = key.Split(".");
                foreach (string k in keys) {
                    if (((JObject)jToken).ContainsKey(k)) {
                        jToken = jToken[k];
                    } else {
                        return res;
                    }
                }
            }


            if (jToken is JArray) {
                JArray arr = (JArray)jToken;
                for (int i = 0; i < arr.Count; i++) {
                    JObject obj = (JObject)arr[i];
                    res.Add(create2<T>(obj));
                }
            } else {
                res.Add(create2<T>((JObject)jToken));
            }



            return res;
        }

        static T create2<T>(JObject jsonObject) {
            Type type = typeof(T);
            T t = (T)Activator.CreateInstance(type);
            FieldInfo[] fields = type.GetFields();
            foreach (FieldInfo f in fields) {
                String mappingName = f.Name;
                JToken jt = getData(jsonObject, mappingName);
                ;
                if (jt != null) {
                    var v = jt.ToObject(f.FieldType);
                    if (v == null && f.FieldType.Name.ToLower() == "string") {
                        v = jt.ToString();
                    }
                    f.SetValue(t, v);
                }


            }
            return t;
        }


        static JToken getData(JObject jsonObject, String n) {

            if (jsonObject.ContainsKey(n)) {
                return jsonObject[n];
            }

            return null;

        }



        static JToken getData(JObject jsonObject ,MappingNameAttribute mappingName) {
            String[] names = mappingName.getNames();
            foreach( String n in names ) {
                if( jsonObject.ContainsKey(n) ) {
                    return jsonObject[n];
                }
            }
            return null;

        }

        public static Object toOb(BsonDocument doc) {
            Dictionary<String ,object> v = new Dictionary<String ,object>();
            IEnumerable<BsonElement> list = doc.Elements;
            foreach( BsonElement e in list ) {
                var val = e.Value;
                if( val.IsBsonDateTime ) {
                    BsonDateTime va = val.AsBsonDateTime;
                    v.Add(e.Name ,va.ToLocalTime());
                } else {
                    v.Add(e.Name ,e.Value.ToString());
                }


            }
            return v;
        }
        public static Dictionary<String ,object> toOb2(BsonDocument doc) {
            Dictionary<String ,object> data = new Dictionary<String ,object>();
            IEnumerable<BsonElement> list = doc.Elements;
            foreach( BsonElement e in list ) {
                var v = e.Value;
                if( v.IsBsonDocument ) {
                    data.Add(e.Name ,toOb2(( BsonDocument ) v));
                } else if( v.IsBsonArray ) {
                    BsonArray array = v.AsBsonArray;
                    List<object> l = new List<object>();
                    foreach( BsonValue eChild in array ) {
                        if( eChild.IsBsonDocument ) {
                            l.Add(toOb2(( BsonDocument ) eChild));
                        } else {
                            l.Add(eChild.ToString());
                        }
                    }
                    data.Add(e.Name ,l);
                } else {
                    data.Add(e.Name ,v.ToString());
                }

            }
            return data;
        }
        public static BsonDocument def(BsonDocument his ,BsonDocument nowDoc) {
            BsonDocument bd = new BsonDocument();
            ;
            IEnumerable<BsonElement> elements = nowDoc.Elements;
            foreach( BsonElement be in elements ) {
                String name = be.Name;
                BsonValue oldvalue = his[name];
                BsonValue nowv = be.Value;
                var defValue = def2(oldvalue ,nowv ,name);
                if( defValue != null ) {
                    bd.Add(name ,defValue);
                }

            }
            return bd;
        }

        static BsonValue def2(BsonValue oldvalue ,BsonValue nowv ,String name) {
            if( nowv.IsBsonArray ) {
                BsonArray array = nowv.AsBsonArray;
                BsonArray arrayold = oldvalue.AsBsonArray;
                if( array.Count != arrayold.Count ) {
                    return nowv;
                } else {
                    BsonArray arrayNew = new BsonArray();
                    for( int i = 0;i < array.Count;i++ ) {
                        BsonDocument bdc = def(arrayold[i].AsBsonDocument ,array[i].AsBsonDocument);
                        if( bdc.ElementCount != 0 ) {
                            arrayNew.Add(bdc);
                        }
                    }
                    if( arrayNew.Count != 0 ) {
                        return arrayNew;
                    }

                }
            } else if( nowv.IsBsonDocument ) {
                BsonDocument defValue = def(oldvalue.AsBsonDocument ,nowv.AsBsonDocument);
                if( defValue.ElementCount != 0 ) {
                    return defValue;
                }
            } else {

                return valueChange(oldvalue.ToString() ,nowv.ToString() ,name);


            }
            return null;
        }
        public static BsonDocument getDoc(BsonDocument doc ,string name) {
            if( doc != null && doc.Contains(name) ) {
                return doc[name].AsBsonDocument;
            }
            return null;
        }
        public static String getStr(BsonDocument doc ,string name) {
            if( doc != null && doc.Contains(name) ) {
                return doc[name].ToString();
            }
            return "";
        }

        public static DateTime getDate(BsonDocument doc ,string name) {
            if( doc != null && doc.Contains(name) ) {
                BsonValue bv = doc["ticks"];
                if( bv.IsBsonDateTime ) {
                    return bv.AsBsonDateTime.ToLocalTime();
                }

            }
            throw new Exception(name + "转换日期异常");
        }
        public static BsonDocument getDef(BsonDocument his ,BsonDocument document ,List<String> nameList ,List<String> nameList2) {
            BsonDocument res = null;
            BsonDocument bd = new BsonDocument();
            foreach( String name in nameList ) {
                String oldvalue = getStr(his ,name);
                String nowv = getStr(document ,name);
                var defValue = valueChange(oldvalue ,nowv ,name);
                if( defValue != null ) {
                    res = bd;
                    bd.Add(name ,defValue);
                } else {
                    // bd.Add(name ,nowv);
                }
            }
            if( res != null ) {
                copyValue(document ,nameList2 ,res);
            }
            return res;
        }

        public static BsonDocument getDefV(BsonDocument his ,BsonDocument document ,List<String> nameList ,List<String> nameList2) {
            BsonDocument res = null;
            BsonDocument bd = new BsonDocument();
            foreach( String name in nameList ) {
                String oldvalue = getStr(his ,name);
                String nowv = getStr(document ,name);
                var defValue = newValue(oldvalue ,nowv ,name);
                if( defValue != null ) {
                    res = bd;
                    bd.Add(name ,defValue);
                } else {
                    // bd.Add(name ,nowv);
                }
            }
            if( res != null ) {
                copyValue(document ,nameList2 ,res);
            }
            return res;
        }

        public static BsonDocument copyValue(BsonDocument document ,List<String> nameList2 ,BsonDocument res = null) {
            if( res == null ) {
                res = new BsonDocument();

            }
            foreach( String name in nameList2 ) {
                if( document.Contains(name)&& !res.Contains(name)) {
                    res.Add(name ,document[name]);
                }
            }
            return res;

        }


        public static BsonValue valueChange(String oldvalue ,String nowv ,String name) {
            if( String.IsNullOrWhiteSpace(oldvalue) && String.IsNullOrWhiteSpace(nowv) ) {
                return null;
            }
            oldvalue = String.IsNullOrWhiteSpace(oldvalue) ? "0" : oldvalue;
            if( oldvalue != nowv ) {
                return BsonValue.Create(oldvalue + "->" + nowv);
            }
            return null;
        }

        public static BsonValue newValue(String oldvalue ,String nowv ,String name) {
            if( String.IsNullOrWhiteSpace(oldvalue) && String.IsNullOrWhiteSpace(nowv) ) {
                return null;
            }
            oldvalue = String.IsNullOrWhiteSpace(oldvalue) ? "0" : oldvalue;
            if( oldvalue != nowv ) {
                return BsonValue.Create(nowv);
            }
            return null;
        }
        public static BsonDocument getGSBsonDocument(Object s) {
            // get source PropertyInfos
            PropertyInfo[] pps = MyReflectionUtil. GetPropertyInfos(s.GetType());
            BsonDocument bd = new BsonDocument();

            foreach (var pp in pps) {
                object v = pp.GetValue(s, null);
                if (v == null) {
                    continue;
                }
                bd[pp.Name] = obj2BsonValue(v);

            }
            return bd;

        }
        static public BsonDocument getBsonDocument(Object obj) {
            BsonDocument bd = new BsonDocument();
            Type t = obj.GetType();
            Dictionary<string, DateTime> res = new Dictionary<string, DateTime>();
            FieldInfo[] fields = t.GetFields();
            Type tmp = typeof(DateTime);
            foreach (FieldInfo fi in fields) {
                Object v = fi.GetValue(obj);

                if (v == null) {
                    continue;
                }
                bd[fi.Name] = obj2BsonValue(v);

            }

            return bd;
        }

        static BsonValue obj2BsonValue(object v) {

            if (v == null) {
                return null;
            }
            if (v is DateTime) {
                return (DateTime)v;
            } else if (v is ValueType) {
                return BsonValue.Create(v);

            } else if (v is string) {
                return (string)v;
            } else {

                return getBsonDocument(v);
            }

        }
    }
}
